物联网平台提供设备影子功能,用于缓存设备状态。设备在线时,可以直接获取云端指令;设备离线时,上线后可以主动拉取云端指令。 设备影子是一个 JSON 文档,用于存储设备上报状态、应用程序期望状态信息。 每个设备有且只有一个设备影子,设备可以通过MQTT获取和设置设备影子来同步状态,该同步可以是影子同步给设备,也可以是设备同步给影子。
场景1:网络不稳定,设备频繁上下线。 由于网络不稳定,设备频繁上下线。应用程序发出需要获取当前的设备状态请求时,设备掉线,无法获取设备状态,但下一秒设备又连接成功,应用程序无法正确发起请求。 使用设备影子机制存储设备最新状态,一旦设备状态产生变化,设备会将状态同步到设备影子。应用程序在请求设备当前状态时,只需要获取影子中的状态即可,不需要关心设备是否在线。
场景2:多程序同时请求获取设备状态。 如果设备网络稳定,很多应用程序请求获取设备状态,设备需要根据请求响应多次,即使响应的结果是一样的,设备本身处理能力有限,无法负载被请求多次的情况。 使用设备影子机制,设备只需要主动同步状态给设备影子一次,多个应用程序请求设备影子获取设备状态,即可获取设备最新状态,做到应用程序和设备的解耦。
场景3:设备掉线。
您可以在设备详情页,查看设备影子信息,更新设备影子状态。
操作步骤:
1.登陆平台设备管理界面
2.单击对应设备的查看设备列表
按钮, 进入设备列表界面
3.单击对应设备的详情
按钮, 进入设备详情页
4.单击设备影子
5.单击编辑镜像
,填入期望设备状态。设备影子文档格式,请参见设备影子JSON详解。
设备影子JSON文档示例:
{
"deviceId":10218769,
"createTime":1586830856,
"connectionSta te":0,
"properties":{
"timestamp":1586832673,
"version":1,
"state":{
"desired":{
"color":"red"
},
"reported":{
"color":"green"
}
},
"metadata":{
"desired":{
"color":1586832673
},
"reported":{
"color":1586832673
}
}
}
}
JSON属性说明
属性 | 描述 |
---|---|
desired | 设备的预期状态。仅当设备影子文档具有预期状态时,才包含desired部分。应用程序向desired部分写入数据,更新事物的状态,而无需直接连接到该设备。 |
reported | 设备的报告状态。设备可以在reported部分写入数据,报告其最新状态。应用程序可以通过读取该参数值,获取设备的状态。JSON文档中也可以不包含reported部分,没有reported部分的文档同样为有效影子JSON文档。 |
metadata | 当用户更新设备状态文档后,设备影子服务会自动更新metadata的值。设备状态的元数据的信息包含以 Epoch 时间表示的每个属性的时间戳,用来获取准确的更新时间。 |
createTime | 影子创建时间 |
deviceId | 设备ID |
connectionState | 设备连接状态 |
timestamp | 影子文档的最新更新时间 |
说明
设备影子支持数组。更新数组时必须全量更新,不能只更新数组的某一部分。
更新数组数据示例:
初始状态:
{
"desired" : { "colors" : ["RED", "GREEN", "BLUE" ] }
}
更新:
{
"desired" : { "colors" : ["RED"] }
}
最终状态:
{
"desired" : { "colors" : ["RED"] }
}
设备影子数据通过Topic进行流转。本文介绍设备影子数据流转,包括:设备上报状态到设备影子,应用程序更改设备状态,设备离线再上线后主动获取设备影子信息,和设备端请求删除设备影子中的属性信息。
物联网平台已为每个设备预定义了四个Topic,用于实现数据流转。您可以直接使用。
shadow/update/pid/${产品ID}/devkey/${设备ID}
设备发布消息到此Topic。物联网平台收到该Topic的消息后,将消息中的状态更新到设备影子中。shadow/update/resp/pid/${产品ID}/devkey/${设备ID}
设备订阅此topic获取更新结果
shadow/get/${产品ID}/${设备ID}
设备向此topic发起获取设备影子请求
shadow/get/resp/${产品ID}/${设备ID}
设备订阅此topic获取请求结果, 应用程序更新设备影子通过此topic下发给设备以下章节中,以某个具体设备为例,说明设备、设备影子以及应用程序之间的通信。
示例中,产品ID是100657;设备ID是10218769。设备以QoS=1发布消息和订阅两个设备影子Topic:
shadow/update/resp/pid/100657/devkey/10218769
,
shadow/get/resp/pid/100657/devkey/10218769
。
示例主要讲解四大部分内容:设备主动上报状态,应用程序改变设备状态,设备主动获取影子内容,和设备主动删除影子属性。
设备在线时,主动上报设备状态到影子,应用程序主动获取设备影子状态。
1.当设备上线时,使用Topic shadow/update/pid/100657/devkey/10218769
上报最新状态到影子。
发送的JSON消息格式:
{
"method": "update",
"state": {
"reported": {
"color": "red"
}
},
"version": 1
}
上报参数说明
属性 | 描述 |
---|---|
method | 表示设备或者应用程序请求设备影子时的操作类型。当执行更新操作时,method为必填字段,设置为update。 |
state | 表示设备发送给设备影子的状态信息。reported为必填字段,状态信息会同步更新到设备影子的reported部分。 |
version | 表示设备影子检查请求中的版本信息。只有当新版本大于当前版本时,设备影子才会接收设备端的请求,并更新设备影子版本。如果version设置为-1时,表示将设备影子版本号重置为0。 |
2.设备影子接收到设备上报的状态数据后,更新影子文档
{
"deviceId":10218769,
"createTime":1586830856,
"connectionState":1,
"properties":{
"timestamp":1586830856,
"version":2,
"state":{
"desired":{
},
"reported":{
"color":"red"
}
},
"metadata":{
"desired":{
},
"reported":{
"color":1586833593
}
}
}
}
3.影子文档更新后,设备影子会返回结果给设备,即发送消息到设备订阅的Topic: shadow/update/resp/pid/100657/devkey/10218769
中。
若更新成功,发送到该Topic中的消息为:
{
"method": "reply",
"payload": {
"status": "success",
"version": 1
},
"timestamp": 1586833593
}
若更新失败,发送到该Topic中的消息为:
{
"method": "reply",
"payload": {
"status": "error",
"content": {
"errorcode": "${errorcode}",
"errormessage": "${errormessage}"
},
"timestamp": 1469564576
}
错误码说明
errorCode | errorCode |
---|---|
1001 | 无效的设备ID |
1002 | 内部错误 |
1003 | 参数格式错误 |
1004 | properties参数为空 |
1005 | state参数为空 |
1006 | desired参数为空 |
1007 | version参数为空 |
1008 | 请求的版本号小于影子的版本号 |
1009 | reported参数为空 |
1010 | 无效的reported参数 |
1011 | 设备不存在 |
1012 | 请求设备没有设备影子 |
1013 | 无效的desired参数 |
用户通过界面设备影子模块下发期望状态给设备影子,设备影子再将文档下发给设备端。设备根据影子更新状态,并上报最新状态至影子。
1.用户通过界面设备影子模块下发消息要求更改设备状态,例如要求将设备的color属性值改为green。
2.设备影子接收到更新请求,更新其影子文档为:
{
"deviceId":10218769,
"createTime":1586830856,
"connectionState":1,
"properties":{
"timestamp":1586830856,
"version":3,
"state":{
"desired":{
"color":"green"
},
"reported":{
"color":"red"
}
},
"metadata":{
"desired":{
"color":1586836789
},
"reported":{
"color":1586833593
}
}
}
3.设备影子更新完成后,发送返回结果到Topic: shadow/get/resp/pid/100657/devkey/10218769
中。返回结果信息构成由设备影子决定。
{
"method":"reply",
"payload":{
"status": "success",
"state": {
"desired": {
"color": "green",
},
"reported": {
"color": "red"
}
},
"metadata": {
"desired": {
"color": {
"timestamp": 1469564492
},
},
"reported": {
"color": {
"timestamp": 1469564492
}
}
}
},
"timestamp": 1469564492,
"version": 1
}
4.如果设备在线,并且订阅了Topic shadow/get/resp/pid/100657/devkey/10218769
,则会立即收到消息。收到消息后,根据请求文档中desired的值,将设备color属性变成green。
设备更新完状态后,上报最新状态到物联网平台。
{
"method": "update",
"state": {
"reported": {
"color": "green"
}
},
"version": 4
}
设备再次上线后,将主动获取设备影子内容。
1.设备主动发送以下消息到Topic shadow/get/pid/100657/devkey/10218769
中,请求获取设备影子中保存的最新状态。
{
"method": "get"
}
2.当设备影子收到这条消息后,发送最新状态到Topic: shadow/get/resp/pid/100657/devkey/10218769
。设备通过订阅该Topic获取最新状态。消息内容如下:
{
"method":"reply",
"payload":{
"status": "success",
"state": {
"desired": {
"color": "green",
},
"reported": {
"color": "red"
}
},
"metadata": {
"desired": {
"color": {
"timestamp": 1469564492
},
},
"reported": {
"color": {
"timestamp": 1469564492
}
}
}
},
"timestamp": 1469564492,
"version": 1
}
若设备端已经是最新状态,设备端可以主动发送指令,删除设备影子中保存的某条属性状态。
{
"method": "delete",
"state": {
"reported": {
"color": "null",
"temperature": "null"
}
},
"version": 1
}
// 删除影子全部属性
{
"method": "delete",
"state": {
"reported": "null"
},
"version": 1
}